<?php
/**
 * This file is part of Hyperf Mall.
 *
 * @link     https://gitee.com/scwlkj/hyperf_mall
 * @contact  hyperf_mall@163.com
 */

namespace App\Repository;

use App\Common\Singleton;
use App\Exception\BaseException;
use App\Model\BaseModel;
use App\Utils\Log;
use Hyperf\Database\Model\Builder;

class BaseRepository
{
    use Singleton;

    /** @var BaseModel */
    protected $model;

    protected $fields;

    public function __call($method, $arguments)
    {
        if (method_exists(__CLASS__, $method)) {
            return $this->$method(...$arguments);
        }

        throw new BaseException(BaseException::BASE_ERROR, sprintf('%s未定义%s函数', __CLASS__, $method));
    }

    /**
     * @param array $conditions [['key' => value], 'key' => [value1, value2], ['key', 'operator', value]]
     * 'key' => value               用于等于查询
     * 'key' => [value1, value2]    用于whereIn查询
     * ['key', 'operator', value]   用于操作符查询
     * operator： '=', '<', '>', '<=', '>=', '<>', '!=', 'like', 'like binary', 'not like', 'between', 'ilike',
     *            '&', '|', '^', '<<', '>>', 'rlike', 'regexp', 'not regexp', '~', '~*', '!~', '!~*', 'similar to',
     *            'not similar to', 'not ilike', '~~*', '!~~*',
     * @return BaseModel|Builder|\Hyperf\Database\Query\Builder
     */
    protected function _searchFactor($conditions = [])
    {
        $model = $this->model;
        $conditions = array_merge($conditions, $model->getAttributes());

        $whereIn = [];
        $whereBetween = [];
        foreach ($conditions as $key => $val) {
            if(!is_numeric($key) && is_array($val)) {
                $whereIn[$key] = $val;
                unset($conditions[$key]);
            }
        }

        foreach ($conditions as $key => $val) {
            if(is_numeric($key) && $val[1] == 'between' && is_array($val[2])) {
                $whereBetween[$val[0]] = $val[2];
                unset($conditions[$key]);
            }
        }

        if(!empty($conditions))
            $model = $model->where($conditions);

        foreach ($whereIn as $key => $val) {
            $model = $model->whereIn($key, $val);
        }

        foreach ($whereBetween as $key => $val) {
            $model = $model->whereBetween($key, $val);
        }


        return $model;
    }

    /**
     * @param array $conditions
     * @return int
     */
    public function getCount(array $conditions = []): int
    {
        return $this->_searchFactor($conditions)->count();
    }

    /**
     * 通过条件获取单条数据
     * @param array $conditions
     * @param string[] $fields
     * @return array
     */
    public function getOne(array $conditions = [], array $fields = ['*']): array
    {
        $data = $this->_searchFactor($conditions)->first($fields);
        return empty($data) ? [] : $data->toArray();
    }

    /**
     * 通过条件获取多条数据
     * @param array $conditions
     * @param string[] $fields
     * @return array
     */
    public function getRows(array $conditions = [], array $fields = ['*']): array
    {
        return $this->_searchFactor($conditions)->orderByDesc($this->model->getPrimaryKey())->get($fields)->toArray();
    }

    /**
     * 通过条件获取多条数据-分页
     * @param array $conditions
     * @param string[] $fields
     * @param int $page
     * @param int $size
     * @return array
     */
    public function getPageRows(array $conditions = [], array $fields = ['*'], int $page = 1, int $size = 10): array
    {
        $count = $this->_searchFactor($conditions)->count();
        $offset = max(0, ($page-1)*$size);
        $data = $this->_searchFactor($conditions)->orderByDesc($this->model->getPrimaryKey())->offset($offset)->limit($size)->get($fields)->toArray();

        return ['total'=>$count, 'data'=>$data];
    }

    /**
     * 通过条件更新数据
     * @param $conditions
     * @param $data
     * @return bool
     */
    public function updateByConditions($conditions, $data): bool
    {
        if (empty($data))  return false;
        if(!empty($data['delete_time'])) return false;
        $this->model->filterFields($data);
        return $this->_searchFactor($conditions)->update($data);
    }

    /**
     * Notes: 基础添加数据
     * Author: Bruce.z
     * DateTime: 2021/12/21 17:05
     * @param $data
     * @return BaseModel|\Hyperf\Database\Model\Model
     */
    public function baseAdd($data)
    {
        return $this->model->baseAdd($data);
    }

    /**
     * Notes: 批量添加
     * Author: Bruce.z
     * DateTime: 2022/1/25 11:45
     * @param $data
     * @return bool
     */
    public function batchAdd($data)
    {
        return $this->model->insert($data);
    }

    /**
     * Notes: 基础删除数据
     * Author: Bruce.z
     * DateTime: 2021/12/21 17:07
     * @param $id
     * @return int|mixed
     */
    public function baseRemove($id)
    {
        return $this->model->baseRemove($id);
    }

    /**
     * Notes: 批量删除
     * Author: Bruce.z
     * DateTime: 2022/1/13 14:13
     * @param $ids
     * @return int
     */
    public function baseRemoveAll($ids)
    {
        return $this->model->whereIn('id',$ids)->delete();
    }
}
